{
  This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
  the Free Software Foundation; version 2 of the License.
   
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
}

// Copyright (c) 2010 2011 2012 - J. Aldo G. de Freitas Junior

{$mode objfpc}
{$H+}

Unit
	Functions;

Interface

Uses
	Classes,
	BaseException,
	SysUtils,
	{StrUtils,}
	Stacks,
	XMLNodes,
	ExprLoader;

Type
	TNodeFunctions = Class(TStackFunctor)
	Public
		Procedure PushTrue(Var aMessage); Message 'true';
		Procedure PushFalse(Var aMessage); Message 'false';
		Procedure FuncGetProperty(Var aMessage); Message 'getproperty';
		Procedure FuncGetProp(Var aMessage); Message 'get';
		Procedure FuncGetText(Var aMessage); Message 'gettext';
		Procedure FuncGetNodeName(Var aMessage); message 'nodename';
		Procedure FuncGetNodeKind(Var aMessage); Message 'nodekind';
		Procedure FuncGetNodeNumber(Var aMessage); Message 'nodenumber';
		Procedure FuncConcat(Var aMessage); Message 'concat';
		Procedure FuncLineEnd(Var aMessage); Message 'lineend';
	End;

Implementation

// TNodeFunctions

Procedure TNodeFunctions.PushTrue(Var aMessage);
Begin
	Stack.DoPushTrue;
End;

Procedure TNodeFunctions.PushFalse(Var aMessage);
Begin
	Stack.DoPushFalse;
End;

Procedure TNodeFunctions.FuncGetProperty(Var aMessage);
Var
	lDomLoader : TExprRootNode;
	lDom,
	lProp : String;
	lFocused : TXMLNode;
Begin
	Stack.Enter(2);
	Try
		Try
			lProp := Stack.Top.Pop;
			lDom := Stack.Top.Pop;
			lFocused := Stack.Focused;
			lDomLoader := TExprRootNode.Create(Nil);
			lDomLoader.DoLoadDomainName('Function parameter', lDom);
			lDomLoader.PropagateStack(Stack);
			lDomLoader.Evaluate;
			Stack.Top.Push(Stack.Focused.Properties[lProp]);
		Except
		On E: Exception Do
		Begin
			Stack.Top.Push('');
			Raise EInterpreterException.Create(1, 1, 'Function parameter', E);
		End;
	End;
	Finally
		Stack.Focused := lFocused;
		FreeAndNil(lDomLoader);
		Stack.Leave(1);
	End;
End;

Procedure TNodeFunctions.FuncGetProp(Var aMessage);
Begin
	Stack.Enter(1);
	Try
		Try
			Stack.Top.Push(Stack.Focused.GetCurrent.Properties[Stack.Top.Pop]);
		Except
			On E: Exception Do
				Stack.Top.Push('');
		End;
	Finally
		Stack.Leave(1);
	End;
End;

Procedure TNodeFunctions.FuncGetText(Var aMessage);
Var
	lDomLoader : TExprRootNode;
	lDom : String;
	lFocused : TXMLNode;
Begin
	Stack.Enter(1);
	Try
		lDom := Stack.Top.Pop;
		lFocused := Stack.Focused;
		Try
			If lDom <> '' Then
			Begin
				lDomLoader := TExprRootNode.Create(Nil);
				lDomLoader.DoLoadDomainName('Function parameter', lDom);
				lDomLoader.PropagateStack(Stack);
				lDomLoader.Evaluate;
			End;
		Except
			On E: Exception Do
			Begin
				Stack.Top.Push('');
				Raise EInterpreterException.Create(1, 1, 'Function parameter', E);
			End;
		End;
		Stack.Top.Push(Stack.Focused.GetTextChild);
	Finally
		Stack.Focused := lFocused;
		FreeAndNil(lDomLoader);
		Stack.Leave(1);
	End;
End;

Procedure TNodeFunctions.FuncGetNodeName(Var aMessage);
Begin
	Stack.Enter(0);
	Try
		If Stack.Focused.GetPropertyIndex('name') >= 0 Then
			Stack.Top.Push(Stack.Focused.Properties['name'])
		Else
			Stack.Top.Push('');
	Finally
		Stack.Leave(1);
	End;
End;

Procedure TNodeFunctions.FuncGetNodeKind(Var aMessage);
Begin
	Stack.Enter(0);
	Try
		Stack.Top.Push(Stack.Focused.RegisteredName);
	Finally
		Stack.Leave(1);
	End;
End;

Procedure TNodeFunctions.FuncGetNodeNumber(Var aMessage);
Begin
	Try
		Stack.Enter(0);
		Stack.Top.Push(Stack.Focused.GetMyIndex);
	Finally
		Stack.Leave(1);
	End;
End;

Procedure TNodeFunctions.FuncConcat(Var aMessage);
Var
	lResult : String;
	lCtrl : Integer;
Begin
	lResult := '';
	For lCtrl := 0 To Stack.Top.Count - 1 Do
		AppendStr(lResult, Stack.Top.Peek(lCtrl));
	Stack.Top.Push(lResult);
End;

Procedure TNodeFunctions.FuncLineEnd(Var aMessage);
Begin
	Stack.Top.Push(#13#10);
End;

End.
